package cn.itsource.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import cn.itsource.api.openfeign.LoginOpenfeign;
import cn.itsource.constants.CacheConstants;
import cn.itsource.constants.ErrorCode;
import cn.itsource.constants.RConst;
import cn.itsource.pojo.LoginRo;
import cn.itsource.pojo.domain.Driver;
import cn.itsource.mapper.DriverMapper;
import cn.itsource.pojo.domain.DriverAggrement;
import cn.itsource.pojo.domain.DriverSetting;
import cn.itsource.pojo.domain.DriverSummary;
import cn.itsource.pojo.dto.RegisterDto;
import cn.itsource.pojo.ro.DriverOnLine;
import cn.itsource.pojo.ro.GeoRo;
import cn.itsource.pojo.ro.WxChatRegisterRo;
import cn.itsource.result.JSONResult;
import cn.itsource.service.*;
import cn.itsource.utils.BitStatesUtils;
import cn.itsource.utils.NameUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;

import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 司机对象 服务实现类
 * </p>
 *
 * @author whale
 * @since 2024-07-02
 */
@Service
@Slf4j
public class DriverServiceImpl extends ServiceImpl<DriverMapper, Driver> implements IDriverService {

    @Autowired
    private IDriverAggrementService driverAggrementService;

    @Autowired
    private WxChatService wxChatService;

    @Autowired
    private LoginOpenfeign loginOpenfeign;

    @Autowired
    private IDriverSummaryService driverSummaryService;

    @Autowired
    private IDriverSettingService driverSettingService;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    /**
     * 业务逻辑
     * @param registerRo
     * @return
     */
    @Override
    //@Transactional
    @GlobalTransactional

    public JSONResult phoneRegister(WxChatRegisterRo registerRo) {
        RegisterDto wxChatOpenid = wxChatService.getWxChatOpenid(registerRo.getCode());
        //String userPhone = wxChatService.getUserPhone(registerRo.getPhoneCode());
        String userPhone="18234782385";
        //判断存不存在
        Driver one = super.getOne(new LambdaQueryWrapper<Driver>().eq(Driver::getOpenId, wxChatOpenid.getOpenid()));
        if (one == null) {
            initDriver(wxChatOpenid,userPhone);
            loginOpenfeign.createLogin(buildLoginRo(wxChatOpenid,userPhone));
            return JSONResult.message("微信绑定成功");
        }

        return JSONResult.error(ErrorCode.WX_CHAT_REPEAT_ERROR);

    }

    @Override
    public DriverSetting onLine(DriverOnLine driverOnLine) {
        String openid = StpUtil.getExtra("openid").toString();
        //根据openid拿到司机信息
        Driver one = super.getOne(new LambdaQueryWrapper<Driver>().eq(Driver::getOpenId, openid));
        //根据司机id获取司机配置信息
        DriverSetting setting = driverSettingService.getById(one.getId());
        //将司机配置存入缓存里
        String key = String.format(CacheConstants.KEY_DRIVER_ONLINE_SETTING,one.getId());
        redisTemplate.opsForValue().set(key,setting,RConst.Num.INT_5 ,TimeUnit.MINUTES);

        return setting;
    }

    @Override
    public void OffLine() {
        String openid = StpUtil.getExtra("openid").toString();
        //根据openid拿到司机信息
        Driver one = super.getOne(new LambdaQueryWrapper<Driver>().eq(Driver::getOpenId, openid));
        //将司机配置存入缓存里
        String key = String.format(CacheConstants.KEY_DRIVER_ONLINE_SETTING,one.getId());
        redisTemplate.delete(key);
    }

    @Override
    public void geo(GeoRo geoRo) {
        String openid = StpUtil.getExtra("openid").toString();
        //根据openid获取司机信息
        Driver one = super.getOne(new LambdaQueryWrapper<Driver>().eq(Driver::getOpenId, openid));
        //获取小程序 提交的坐标
        Point point = new Point(Double.valueOf(geoRo.getLongitude()), Double.valueOf(geoRo.getLatitude()));
        //将坐标缓存到geo里面
        Long add = redisTemplate.opsForGeo().add(CacheConstants.KEY_DRIVER_GEO, point, one.getId());//处理地理位置的
        //判断是否添加成功
        if (add == RConst.Num.LONG_1) {
            //刷新司机状态
            String key = String.format(CacheConstants.KEY_DRIVER_ONLINE_SETTING, one.getId());
            redisTemplate.expire(key,RConst.Num.INT_5,TimeUnit.MINUTES);
        }
    }

    private static LoginRo buildLoginRo(RegisterDto wxChatOpenid,String phone) {
        LoginRo loginRo = new LoginRo();
        loginRo.setPassword("123345");
        loginRo.setType(RConst.Num.INT_1);
        loginRo.setOpenId(wxChatOpenid.getOpenid());
        loginRo.setUsername(NameUtil.getName());
        loginRo.setPhone(phone);
        loginRo.setAdmin(false);
        return loginRo;
    }

    private void initDriver(RegisterDto registerDto,String phone) {
        Long snowflake = IdUtil.createSnowflake(RConst.Num.INT_1, RConst.Num.INT_1).nextId();
        long state = BitStatesUtils.addState(RConst.Num.INT_0, BitStatesUtils.OP_PHONE);
        long state1 = BitStatesUtils.addState(state, BitStatesUtils.OP_INIT_PAY_PASSWORD);
        Long binaryString = Long.valueOf(Long.toBinaryString(state1));  //转化成二进制
        Driver driver = new Driver();
        driver.setId(snowflake)
                .setCreateTime(new Date())
                .setOpenId(registerDto.getOpenid())
                .setPhone(phone)
                .setBitState(binaryString);

        super.save(driver);

        //合同
        initDriverAggrement(snowflake);

        //当前司机的统计
        DriverSummary driverSummary = new DriverSummary();
        driverSummary.setId(snowflake);
        driverSummaryService.save(driverSummary);

    }

    private void initDriverAggrement(Long snowflake) {
        //合同
        DriverAggrement driverAggrement = new DriverAggrement();
        driverAggrement.setId(IdUtil.createSnowflake(RConst.Num.INT_1, RConst.Num.INT_1).nextId())
                .setDriverId(snowflake)
                .setStatus(RConst.Num.INT_0)
                .setCreateTime(new Date());
        driverAggrementService.save(driverAggrement);
    }


}
